/*
=======================================================================

  Nurse - BOTS
  
=======================================================================
*/
#include "g_local.h"

#include "bots_game2cgame.h"

#include "bg_local.h"
#include "bots_local.h"
#include "bots_nurse.h"

#define	HEALTH_COST		50
#define	MEGA_COST		100
#define	ADRENAL_COST	100
#define REGEN_COST		100

void bots_updateClientData_nurse(gentity_t *self, bots_g2cg_nurse_t *p) {
	if (!self->client)
		return;

	BOTS_SETBIT(p->bits, self->client->qb_poisonMode,	BOTS_G2CG_NURSE_POISON);

	p->weapons.gren1 = p->weapons.gren2	= p->weapons.weaponmode = 0;
	p->weapons.grenademode	= self->client->qb_flashMode;
}

void BOTS_poison (int clientNum)
{
	gentity_t* ent = g_entities + clientNum;

	if (!ent->client)
		return;

	if (ent->bots_class != BOTS_NURSE)
	{
		BOTS_cp_console(clientNum, "Only the Nurse can poison.");
		return;
	}

	ent->client->qb_poisonMode = !ent->client->qb_poisonMode;

	/*
	if (ent->client->qb_poisonMode)
		BOTS_cp_console(clientNum, "Poison activated.");
	else
		BOTS_cp_console(clientNum, "Poison deactivated.");
	*/
}

void BOTS_nurseCreate_setup(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	char*		create_string;
	int			li_modifier;

	if (!ent->client)
		return;

	li_modifier = ent->client->pers.classlevel;

	// check level
	if (li_modifier < 1)
	{
		BOTS_cp_console( clientNum, "You must be at least level 1 to create.");
		return;
	}

	// check ammo
	if (ent->client->ps.ammo[WP_BFG] < HEALTH_COST / li_modifier)
	{
		BOTS_cp_console( clientNum, va("You need at least %i cells to create.", (int)HEALTH_COST / li_modifier));
		return;
	}

	create_string = va("\\h\\1");

	// megahealth
	if (ent->client->ps.ammo[WP_BFG] >= MEGA_COST)
		create_string = va("%s\\m\\1", create_string);
	else
		create_string = va("%s\\m\\2", create_string);

	// adrenaline
	if (ent->client->ps.ammo[WP_BFG] >= ADRENAL_COST)
		create_string = va("%s\\a\\1", create_string);
	else
		create_string = va("%s\\a\\2", create_string);

	// regeneration
	if (ent->client->ps.ammo[WP_BFG] >= REGEN_COST)
		create_string = va("%s\\r\\1", create_string);
	else
		create_string = va("%s\\r\\2", create_string);
	
	// set the menu list
	trap_SetConfigstring(CS_BOTS_MENU + clientNum, create_string);

	// tell cgame we are done so it can send to the UI.
	trap_SendServerCommand(clientNum, "create_data_complete");
}

void BOTS_nurseCreate_item(int clientNum, char* item_string)
{
	gentity_t*	ent = g_entities + clientNum;
	gentity_t*	drop;
	gitem_t*	item;
	vec3_t		angles, velocity, origin, forward;
	int			li_modifier;

	if (!ent->client)
		return;

	li_modifier = ent->client->pers.classlevel;
	if (li_modifier < 1)
		li_modifier = 1;

	if (Q_stricmp (item_string, "health") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) HEALTH_COST / li_modifier;
		item = BG_FindItem("50 Health");
	}
	else if (Q_stricmp (item_string, "megahealth") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) MEGA_COST;
		item = BG_FindItem("Mega Health");
	}
	else if (Q_stricmp (item_string, "adrenaline") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) ADRENAL_COST;
		item = BG_FindItem("Medkit");
	}
	else if (Q_stricmp (item_string, "regeneration") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) REGEN_COST;
		item = BG_FindItem("Regeneration");
	}
	else
	{
		BOTS_cp_console( clientNum, "BAD ITEM FROM MENU.");
		return;
	}

	// taken from Drop_Item

	// set aiming directions
	VectorCopy( ent->s.apos.trBase, angles );

	// set the origin of the launch away from the client
	AngleVectors (ent->client->ps.viewangles, forward, NULL, NULL);
	forward[2] = 0;
	VectorMA(ent->s.pos.trBase, 100, forward, origin);

	angles[PITCH] = 0;	// always forward

	AngleVectors( angles, velocity, NULL, NULL );
	VectorScale( velocity, 150, velocity );
	velocity[2] += 200 + crandom() * 50;

	drop = LaunchItem( item, origin, velocity );

	if (Q_stricmp (item_string, "regeneration") == 0 )
		drop->count    = 15;
}

void BOTS_healradius(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	gentity_t*	player = NULL;
	char		netname[100];
	int			radius;

	if (!ent->client)
		return;

	// only nurses get healradius
	if (ent->bots_class != BOTS_NURSE)
	{
		BOTS_cp_console(clientNum, "Only the Nurse can use healradius.");
		return;
	}

	// check level
	if (ent->client->pers.classlevel < 1)
	{
		BOTS_cp_console( clientNum, "You must be at least level 1 to use healradius.");
		return;
	}

	// check ammo
	if (ent->client->ps.ammo[WP_BFG] < 25 / ent->client->pers.classlevel)
	{
		BOTS_cp_console( clientNum, va("You need at least %i cells to use healradius.", (int)25 / ent->client->pers.classlevel));
		return;
	}
	ent->client->ps.ammo[WP_BFG] -= 25 / ent->client->pers.classlevel;


	// remove the stupid ass colors losers use
	strcpy(netname, ent->client->pers.netname);
	Q_CleanStr(netname);

	radius = 100 * ent->client->pers.classlevel;

	while ((player = findradiusCLIENT(player, ent->s.pos.trBase, radius)) != NULL)
	{
		if (!player->client)
			continue;
		if (player->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;
		if (player == ent)
			continue;
		if (!player->takedamage)
			continue;
		if (player->health <= 0)
			continue;
		if (!OnSameTeam (ent, player))
			continue;
		if (!visible(ent, player))
			continue;	// must see them to heal them

		player->health += 100;
		if (player->health > player->client->ps.stats[STAT_MAX_HEALTH])
			player->health = player->client->ps.stats[STAT_MAX_HEALTH];

		// tell the player they were healed
		// BOTS_cp_console(player->s.clientNum, va("You have been healed by %s", netname));
		G_AddEvent(player,EV_HEALRADIUS,clientNum);
	}
}

void BOTS_heal_setup(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	gentity_t*	player = NULL;
	int			i, j;
	gentity_t*	list[MAX_CLIENTS];  // overkill, but I heard malloc doesn't work
	char*		heal_string = NULL;

	if (!ent->client)
		return;

	// only nurses get healradius
	if (ent->bots_class != BOTS_NURSE)
	{
		BOTS_cp_console(clientNum, "Only the Nurse can use healradius.");
		return;
	}

	// check level
	if (ent->client->pers.classlevel < 4)
	{
		BOTS_cp_console( clientNum, "You must be at least level 4 to remotely heal.");
		return;
	}

	// check ammo
	if (ent->client->ps.ammo[WP_BFG] < 50)
	{
		BOTS_cp_console( clientNum, va("You need at least %i cells to heal.", (int)100 / ent->client->pers.classlevel));
		return;
	}

	// make sure each element is nulled out
	for (j = 0; j < MAX_CLIENTS; j++)
		list[j] = NULL;

	// make the list
	j = 0;
	for(i = 0; i < level.maxclients; i++)
	{
		qboolean alreadySet = qfalse;
		player = g_entities + i;

		if (!player->inuse || !player->client || (player == ent))
			continue; 
		if (player->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;
		if (!OnSameTeam (ent, player))
			continue;
		if (player->health <= 0)
			continue;
		if (player->health >= player->client->ps.stats[STAT_MAX_HEALTH])
			continue;
		if (j == 0)
		{
			list[j] = player;
			j++;
		}
		else
		{
			int k;

			for (k = 0; k < j; k++)
			{
				if (player->health < list[k]->health)
				{
					int h = j;
					for (; h >= k; h--)
						list[h] = list[h-1];
					list[k] = player;
					j++;
					k = j;
					alreadySet = qtrue;
				}
			}
			
			if (!alreadySet)
			{
				list[j] = player;
				j++;
			}
		}
	}// for i < level.maxclients

	for (i = 0; list[i] != NULL; i++)
		heal_string = va("\\name%i\\%i", i, list[i]->s.clientNum);

	// set the list in the config string
	trap_SetConfigstring(CS_BOTS_MENU + clientNum, va("size\\%i%s", i, heal_string));

	// send us back to cgame
	trap_SendServerCommand(clientNum, "heal_list_complete");	
}

void BOTS_heal(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	char		fromUI[MAX_TOKEN_CHARS];
	char		netname[100];
	gentity_t*	player;

	if (trap_Argc() > 1)
		trap_Argv( 1, fromUI, sizeof( fromUI ) );
	else
		G_Printf( S_COLOR_RED "ERROR: invalid heal name\n" );

	player = g_entities + atoi(fromUI);

	// Don't rise the dead :)
	if (!player->client || player->health <= 0)
		return;

	ent->client->ps.ammo[WP_BFG] -= 50;

	// remove the stupid ass colors losers use
	strcpy(netname, ent->client->pers.netname);
	Q_CleanStr(netname);

	player->health = player->client->ps.stats[STAT_MAX_HEALTH];

	// tell the player they were healed
	BOTS_cp_console(player->s.clientNum, va("You have been healed by %s", netname));
}

/////////////////////////////////////////////
//
// BOTS_NurseCommands
//
// This will parse the passed cmd string and call to the correct functions.
// 
// RETURNS
//    qfalse : cmd is not a nurse command
//	  qtrue	 : cmd is a nurse command
//
qboolean BOTS_NurseCommands(int clientNum, char* cmd)
{
	//gentity_t* ent = g_entities + clientNum;

	if (Q_stricmp (cmd, "poison") == 0 )
	{
		BOTS_poison(clientNum);
		return qtrue;
	}
	if (Q_stricmp (cmd, "healradius") == 0 )
	{
		BOTS_healradius(clientNum);
		return qtrue;
	}
	if (Q_stricmp (cmd, "heal") == 0 )
	{
		BOTS_heal_setup(clientNum);
		return qtrue;
	}
	else if (Q_strncmp (cmd, "UI_to_server_heal", strlen ("UI_to_server_heal")) == 0 )
	{
		BOTS_heal(clientNum);
		return qtrue;
	}

	return qfalse;
}

void BOTS_ClientThink_nurse(gentity_t* ent)
{
	if (ent->health <= 0)
		return;

	if (level.time > ent->client->i_lastHealTime) {
		int health = ent->health + (ent->client->pers.classlevel + 1);


		if ( health <= ent->client->ps.stats[STAT_MAX_HEALTH])
			ent->health = health;

		ent->client->i_lastHealTime = level.time + 750;
	}
}
